#include <Windows.h>
#include <MsHTML.h>
#include <atlbase.h>
#include <oleacc.h>
#include <tchar.h>
#include <gdiplus.h>
#include <Exdisp.h>
#include <SHLGUID.h>

#include <memory>
#include <vector>
#include <string>
#include <map>
#include <functional>
#include <algorithm>

#include "Page.h"
#include "Setting.h"
#include "Activity.h"

using namespace std;


CActivity::CActivity(void)
{
}


CActivity::~CActivity(void)
{
}

unique_ptr<CActivity> CActivity::Current() throw()
{
	return unique_ptr<CActivity>(new CActivity());
}

void CActivity::Run(IHTMLDocument2* spDoc) const throw(...)
{
	try
	{
		auto vp = CSetting::Current()->GetPages();

		CComBSTR szUrl;
		spDoc->get_URL(&szUrl);
		if(!szUrl)
			throw wstring(L"Cannot get URL of the page");
		wstring url = szUrl.Detach();

		// find current page;
		auto page = find_if(vp->cbegin(), vp->cend(), [&url](vector<unique_ptr<CPage>>::const_reference p) -> bool {
			// equivalent to url.StartsWith(p->GetUrl(), StringComparison::Ordinal)
			return url.find(p->GetUrl()) == 0;
		});
		if(page == vp->cend())
			throw wstring(L"Current page was not defined. Page->") + url;

		(*page)->Fill(spDoc);
	}
	catch(const wstring& s)
	{
		MessageBoxW(NULL, s.c_str(), L"Information", MB_OK | MB_ICONINFORMATION);
	}
	catch(...)
	{
		MessageBoxW(NULL, L"Unknown exception", L"Information", MB_OK | MB_ICONERROR);
	}
}

void CActivity::Run(IUnknown* pUnknown) const throw(...)
{
	CComQIPtr<IHTMLDocument2> spDoc = GetDocInterface(pUnknown);
	if(!spDoc)
		return;

	Run(spDoc);
}

CComQIPtr<IHTMLDocument2> CActivity::GetDocInterface(IUnknown* pUnknown) const throw(...)
{
	HRESULT hr;
	CComQIPtr<IServiceProvider> spProvider;
	CComDispatchDriver spDisp;
	CComQIPtr<IWebBrowser2> spBrowser;
	CComQIPtr<IHTMLDocument2> spDocument;

	try
	{
		hr = pUnknown->QueryInterface(IID_IServiceProvider, reinterpret_cast<void **>(&spProvider));
		if(FAILED(hr) || !spProvider)
			throw wstring(L"Failed to QueryInterface->IID_IServiceProvider");

		hr = spProvider->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, reinterpret_cast<void **>(&spBrowser));
		if (FAILED(hr) || !spBrowser)
			throw wstring(L"Failed to QueryService->SID_SWebBrowserApp");

		hr = spBrowser->get_Document(&spDisp);
		if (FAILED(hr) || !spDisp)
			throw wstring(L"Failed to get_Document");

		spDocument = spDisp;
		if (!spDocument)
			throw wstring(L"Failed to QueryInterface->IID_IHTMLDocument2");
	}
	catch(const wstring& s)
	{
		MessageBoxW(NULL, s.c_str(), L"Information", MB_OK | MB_ICONERROR);
	}
	catch(...)
	{
		MessageBoxW(NULL, L"Unknown exception", L"Information", MB_OK | MB_ICONERROR);
	}

	return spDocument;
}
